package zcrypto

import (
	"crypto"
	"crypto/md5"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"crypto/x509"
	"encoding/base64"
	"encoding/pem"
	"errors"
	"fmt"
)

func Rsa2Sign(data string, privateKeyStr string) (sign string, err error) {
	var privateKey *rsa.PrivateKey
	var bSign []byte
	mPrivate := ""
	if privateKeyStr[0] != '-' {
		mPrivate = "-----BEGIN PRIVATE KEY-----\r\n" + privateKeyStr + "\r\n-----END PRIVATE KEY-----"
	} else {
		mPrivate = privateKeyStr
	}
	h := sha256.New()
	h.Write([]byte(data))
	hashed := h.Sum(nil)
	blockPri, _ := pem.Decode([]byte(mPrivate))
	if blockPri == nil {
		err = errors.New("private key is invalid")
		return
	}
	privateKey, err = x509.ParsePKCS1PrivateKey(blockPri.Bytes)
	if err != nil {
		return
	}

	bSign, err = rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed)
	if err == nil {
		sign = base64.StdEncoding.EncodeToString(bSign)
	}

	return
}

func VerifyRasForSha256(data, sign, publicKey string) (result bool, err error) {
	var pubInterface interface{}
	result = false
	mPublic := "-----BEGIN PUBLIC KEY-----\r\n" + publicKey + "\r\n-----END PUBLIC KEY-----"
	block, _ := pem.Decode([]byte(mPublic))

	if block == nil {
		err = errors.New("public key is invalid")
		return
	}

	pubInterface, err = x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return
	}

	var bSign []byte
	pub := pubInterface.(*rsa.PublicKey)
	bSign, err = base64.StdEncoding.DecodeString(sign)
	fmt.Printf("%d\n", bSign)
	if err != nil {
		return
	}

	h := sha256.New()
	h.Write([]byte(data))
	hashed := h.Sum(nil)

	err = rsa.VerifyPKCS1v15(pub, crypto.SHA256, hashed, bSign)
	result = err == nil

	return
}

func VerifyRasForMd5(data, sign, publicKey string) (result bool, err error) {
	var pubInterface interface{}
	result = false
	mPublic := "-----BEGIN PUBLIC KEY-----\r\n" + publicKey + "\r\n-----END PUBLIC KEY-----"
	block, _ := pem.Decode([]byte(mPublic))

	if block == nil {
		err = errors.New("public key is invalid")
		return
	}

	pubInterface, err = x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return
	}

	var bSign []byte
	pub := pubInterface.(*rsa.PublicKey)
	bSign, err = base64.StdEncoding.DecodeString(sign)

	if err != nil {
		return
	}

	h := md5.New()
	h.Write([]byte(data))
	hashed := h.Sum(nil)

	err = rsa.VerifyPKCS1v15(pub, crypto.MD5, hashed, bSign)
	result = err == nil

	return
}

func RsaEncrypt(originalData, publicKey string) (sign string, err error) {
	publicKey = "-----BEGIN PUBLIC KEY-----\r\n" + publicKey + "\r\n-----END PUBLIC KEY-----"

	//解密pem格式的公钥
	var block *pem.Block
	data := []byte(publicKey)
	block, _ = pem.Decode(data)
	if block == nil {
		return "", errors.New("public key error")
	}
	// 解析公钥
	var pubInterface interface{}
	pubInterface, err = x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return "", err
	}
	// 类型断言
	pub := pubInterface.(*rsa.PublicKey)
	//加密
	data, err = rsa.EncryptPKCS1v15(rand.Reader, pub, []byte(originalData))
	sign = base64.StdEncoding.EncodeToString(data)
	return
}

func RasPCK8Sign(waitSgin, privateStr string) (sign string, e error) {
	// 解析 PKCS#8 格式的私钥
	privateKey, err := ParsePKCS8PrivateKey([]byte(privateStr))
	if err != nil {
		return "", err
	}

	// 计算数据的 SHA256 散列
	hash := sha256.Sum256([]byte(waitSgin))

	// 使用 RSA 私钥对散列进行签名
	signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hash[:])
	if err != nil {
		return "", err
	}

	// 将签名编码为 Base64 字符串
	signatureBase64 := base64.StdEncoding.EncodeToString(signature)

	return signatureBase64, nil
}

func ParsePKCS8PrivateKey(pkcs8PrivateKey []byte) (*rsa.PrivateKey, error) {
	// 解码 PEM 格式的数据块
	block, _ := pem.Decode(pkcs8PrivateKey)
	if block == nil {
		return nil, errors.New("failed to decode PEM block containing private key")
	}

	// 解析 PKCS#8 格式的私钥
	privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
	if err != nil {
		return nil, err
	}

	// 检查私钥类型
	switch key := privateKey.(type) {
	case *rsa.PrivateKey:
		return key, nil
	//case *ecdsa.PrivateKey:
	//	return privateKey, nil
	default:
		return nil, errors.New("unsupported private key type")
	}
}
